1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.sun.jmx.mbeanserver;
27
28 import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
29 import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
30 import java.lang.annotation.Annotation;
31 import java.lang.reflect.GenericArrayType;
32 import java.lang.reflect.InvocationTargetException;
33 import java.lang.reflect.Method;
34 import java.lang.reflect.ParameterizedType;
35 import java.lang.reflect.Type;
36 import javax.management.Descriptor;
37 import javax.management.ImmutableDescriptor;
38 import javax.management.MBeanAttributeInfo;
39 import javax.management.MBeanException;
40 import javax.management.MBeanOperationInfo;
41 import javax.management.MBeanParameterInfo;
42 import javax.management.NotCompliantMBeanException;
43 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
44 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
45 import javax.management.openmbean.OpenMBeanParameterInfo;
46 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
47 import javax.management.openmbean.OpenType;
48
49
50
51
52
53
54 class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
55 private static final MXBeanIntrospector instance = new MXBeanIntrospector();
56
57 static MXBeanIntrospector getInstance() {
58 return instance;
59 }
60
61 @Override
62 PerInterfaceMap<ConvertingMethod> getPerInterfaceMap() {
63 return perInterfaceMap;
64 }
65
66 @Override
67 MBeanInfoMap getMBeanInfoMap() {
68 return mbeanInfoMap;
69 }
70
71 @Override
72 MBeanAnalyzer<ConvertingMethod> getAnalyzer(Class<?> mbeanInterface)
73 throws NotCompliantMBeanException {
74 return MBeanAnalyzer.analyzer(mbeanInterface, this);
75 }
76
77 @Override
78 boolean isMXBean() {
79 return true;
80 }
81
82 @Override
83 ConvertingMethod mFrom(Method m) {
84 return ConvertingMethod.from(m);
85 }
86
87 @Override
88 String getName(ConvertingMethod m) {
89 return m.getName();
90 }
91
92 @Override
93 Type getGenericReturnType(ConvertingMethod m) {
94 return m.getGenericReturnType();
95 }
96
97 @Override
98 Type[] getGenericParameterTypes(ConvertingMethod m) {
99 return m.getGenericParameterTypes();
100 }
101
102 @Override
103 String[] getSignature(ConvertingMethod m) {
104 return m.getOpenSignature();
105 }
106
107 @Override
108 void checkMethod(ConvertingMethod m) {
109 m.checkCallFromOpen();
110 }
111
112 @Override
113 Object invokeM2(ConvertingMethod m, Object target, Object[] args,
114 Object cookie)
115 throws InvocationTargetException, IllegalAccessException,
116 MBeanException {
117 return m.invokeWithOpenReturn((MXBeanLookup) cookie, target, args);
118 }
119
120 @Override
121 boolean validParameter(ConvertingMethod m, Object value, int paramNo,
122 Object cookie) {
123 if (value == null) {
124
125
126
127
128 Type t = m.getGenericParameterTypes()[paramNo];
129 return (!(t instanceof Class<?>) || !((Class<?>) t).isPrimitive());
130 } else {
131 Object v;
132 try {
133 v = m.fromOpenParameter((MXBeanLookup) cookie, value, paramNo);
134 } catch (Exception e) {
135
136
137 return true;
138 }
139 return isValidParameter(m.getMethod(), v, paramNo);
140 }
141 }
142
143 @Override
144 MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
145 ConvertingMethod getter, ConvertingMethod setter) {
146
147 final boolean isReadable = (getter != null);
148 final boolean isWritable = (setter != null);
149 final boolean isIs = isReadable && getName(getter).startsWith("is");
150
151 final String description = attributeName;
152
153 final OpenType<?> openType;
154 final Type originalType;
155 if (isReadable) {
156 openType = getter.getOpenReturnType();
157 originalType = getter.getGenericReturnType();
158 } else {
159 openType = setter.getOpenParameterTypes()[0];
160 originalType = setter.getGenericParameterTypes()[0];
161 }
162 Descriptor descriptor = typeDescriptor(openType, originalType);
163 if (isReadable) {
164 descriptor = ImmutableDescriptor.union(descriptor,
165 getter.getDescriptor());
166 }
167 if (isWritable) {
168 descriptor = ImmutableDescriptor.union(descriptor,
169 setter.getDescriptor());
170 }
171
172 final MBeanAttributeInfo ai;
173 if (canUseOpenInfo(originalType)) {
174 ai = new OpenMBeanAttributeInfoSupport(attributeName,
175 description,
176 openType,
177 isReadable,
178 isWritable,
179 isIs,
180 descriptor);
181 } else {
182 ai = new MBeanAttributeInfo(attributeName,
183 originalTypeString(originalType),
184 description,
185 isReadable,
186 isWritable,
187 isIs,
188 descriptor);
189 }
190
191
192
193 return ai;
194 }
195
196 @Override
197 MBeanOperationInfo getMBeanOperationInfo(String operationName,
198 ConvertingMethod operation) {
199 final Method method = operation.getMethod();
200 final String description = operationName;
201
202
203
204
205
206 final int impact = MBeanOperationInfo.UNKNOWN;
207
208 final OpenType<?> returnType = operation.getOpenReturnType();
209 final Type originalReturnType = operation.getGenericReturnType();
210 final OpenType<?>[] paramTypes = operation.getOpenParameterTypes();
211 final Type[] originalParamTypes = operation.getGenericParameterTypes();
212 final MBeanParameterInfo[] params =
213 new MBeanParameterInfo[paramTypes.length];
214 boolean openReturnType = canUseOpenInfo(originalReturnType);
215 boolean openParameterTypes = true;
216 Annotation[][] annots = method.getParameterAnnotations();
217 for (int i = 0; i < paramTypes.length; i++) {
218 final String paramName = "p" + i;
219 final String paramDescription = paramName;
220 final OpenType<?> openType = paramTypes[i];
221 final Type originalType = originalParamTypes[i];
222 Descriptor descriptor =
223 typeDescriptor(openType, originalType);
224 descriptor = ImmutableDescriptor.union(descriptor,
225 Introspector.descriptorForAnnotations(annots[i]));
226 final MBeanParameterInfo pi;
227 if (canUseOpenInfo(originalType)) {
228 pi = new OpenMBeanParameterInfoSupport(paramName,
229 paramDescription,
230 openType,
231 descriptor);
232 } else {
233 openParameterTypes = false;
234 pi = new MBeanParameterInfo(
235 paramName,
236 originalTypeString(originalType),
237 paramDescription,
238 descriptor);
239 }
240 params[i] = pi;
241 }
242
243 Descriptor descriptor =
244 typeDescriptor(returnType, originalReturnType);
245 descriptor = ImmutableDescriptor.union(descriptor,
246 Introspector.descriptorForElement(method));
247 final MBeanOperationInfo oi;
248 if (openReturnType && openParameterTypes) {
249
250
251
252
253
254
255
256
257 final OpenMBeanParameterInfo[] oparams =
258 new OpenMBeanParameterInfo[params.length];
259 System.arraycopy(params, 0, oparams, 0, params.length);
260 oi = new OpenMBeanOperationInfoSupport(operationName,
261 description,
262 oparams,
263 returnType,
264 impact,
265 descriptor);
266 } else {
267 oi = new MBeanOperationInfo(operationName,
268 description,
269 params,
270 openReturnType ?
271 returnType.getClassName() :
272 originalTypeString(originalReturnType),
273 impact,
274 descriptor);
275 }
276
277 return oi;
278 }
279
280 @Override
281 Descriptor getBasicMBeanDescriptor() {
282 return new ImmutableDescriptor("mxbean=true",
283 "immutableInfo=true");
284 }
285
286 @Override
287 Descriptor getMBeanDescriptor(Class<?> resourceClass) {
288
289
290
291
292
293
294 return ImmutableDescriptor.EMPTY_DESCRIPTOR;
295 }
296
297 private static Descriptor typeDescriptor(OpenType<?> openType,
298 Type originalType) {
299 return new ImmutableDescriptor(
300 new String[] {"openType",
301 "originalType"},
302 new Object[] {openType,
303 originalTypeString(originalType)});
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319 private static boolean canUseOpenInfo(Type type) {
320 if (type instanceof GenericArrayType) {
321 return canUseOpenInfo(
322 ((GenericArrayType) type).getGenericComponentType());
323 } else if (type instanceof Class<?> && ((Class<?>) type).isArray()) {
324 return canUseOpenInfo(
325 ((Class<?>) type).getComponentType());
326 }
327 return (!(type instanceof Class<?> && ((Class<?>) type).isPrimitive()));
328 }
329
330 private static String originalTypeString(Type type) {
331 if (type instanceof Class<?>)
332 return ((Class<?>) type).getName();
333 else
334 return typeName(type);
335 }
336
337 static String typeName(Type type) {
338 if (type instanceof Class<?>) {
339 Class<?> c = (Class<?>) type;
340 if (c.isArray())
341 return typeName(c.getComponentType()) + "[]";
342 else
343 return c.getName();
344 } else if (type instanceof GenericArrayType) {
345 GenericArrayType gat = (GenericArrayType) type;
346 return typeName(gat.getGenericComponentType()) + "[]";
347 } else if (type instanceof ParameterizedType) {
348 ParameterizedType pt = (ParameterizedType) type;
349 StringBuilder sb = new StringBuilder();
350 sb.append(typeName(pt.getRawType())).append("<");
351 String sep = "";
352 for (Type t : pt.getActualTypeArguments()) {
353 sb.append(sep).append(typeName(t));
354 sep = ", ";
355 }
356 return sb.append(">").toString();
357 } else
358 return "???";
359 }
360
361 private final PerInterfaceMap<ConvertingMethod>
362 perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
363
364 private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
365 }